// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

/**
 * Flash executable runtime initialization code.
 */

  // NOTE: The "ax" flag below is necessary to ensure that this section 
  // is allocated space in ROM by the linker.
  .section .crt, "ax"

  .extern main

/**
 * Callable entry point for flash.
 *
 * This sets up the stack, zeroes `.bss`, and sets up `.data`.
 * It then jumps into main.
 */
_start:
  .globl _start

  // Set up the stack. We have no expectation that the rom that
  // jumps here will have the correct stack start linked in.
  la sp, _stack_start

  // Set up the global pointer. This requires that we disable linker relaxations
  // (or it will be relaxed to `mv gp, gp`).
  .option push
  .option norelax
  la gp, __global_pointer$
  .option pop

  // Set up the new interrupt vector.
  la   t0, _vectors_start
  csrw mtvec, t0

  // Zero out the `.bss` segment.
  //
  // We use `t0` and `t1` to represent the start and end pointers
  // of `.bss`.
  la  t0, _bss_start
  la  t1, _bss_end
  bge t0, t1, bss_zero_loop_end
bss_zero_loop:
  sw    zero, 0(t0)
  addi  t0, t0, 0x4
  ble   t0, t1, bss_zero_loop
bss_zero_loop_end:

  // Zero out the stack
  //
  // We use `t0` and `t1` to represent the start and end pointers of the stack.
  // As the stack grows downwards and we zero going forwards the start pointer
  // starts as _stack_end and the end pointer at _stack_start - 4
  la  t0, _stack_end
  la  t1, (_stack_start - 4)
  bge t0, t1, stack_zero_loop_end
stack_zero_loop:
  sw    zero, 0(t0)
  addi  t0, t0, 0x4
  ble   t0, t1, stack_zero_loop
stack_zero_loop_end:

  // Initialize the `.data` segment from the `.idata` segment.
  //
  // We use `t0` and `t1` to represent the start and end pointers
  // of `.data`, `t2` to represent the start pointer of `.idata`
  // (which has the same length as `.data`) and `t3` is a scratch
  // register for the copy.
  la  t0, _data_start
  la  t1, _data_end
  la  t2, _data_init_start
  bge t0, t1, data_copy_loop_end
data_copy_loop:
  lw   t3, 0(t2)
  sw   t3, 0(t0)
  addi t0, t0, 0x4
  addi t2, t2, 0x4
  ble  t0, t1, data_copy_loop
data_copy_loop_end:

  // Jump into the C program entry point. This is your standard
  // C `main()`, so we need to pass dummy values for `argc` and `argv`.
  li   a0, 0x0  // argc = 0
  li   a1, 0x0  // argv = NULL
  call main

  // Loop forever if main somehow returns.
1:
  wfi
  j 1b
